//
//  LAGGemotry.c
//  LAMapBasicDemo
//
//  Created by 罗亮富 on 2017/10/15.
//  Copyright © 2017年 2Bulu. All rights reserved.
//

#include "LAGGeometry.h"

#include <stdio.h>
#include <math.h>

//#define PI                      3.1415926

//double radian(double d);
//double get_distance(double lat1, double lng1, double lat2, double lng2);

// 求弧度
double radian(double d)
{
    return d* M_PI / 180.0;   //角度1˚ = π / 180
}

//计算距离
double get_distance(double lat1, double lng1, double lat2, double lng2)
{
    double radLat1 = radian(lat1);
    double radLat2 = radian(lat2);
    double a = radLat1 - radLat2;
    double b = radian(lng1) - radian(lng2);
    
    double dst = 2 * asin((sqrt(pow(sin(a / 2), 2) + cos(radLat1) * cos(radLat2) * pow(sin(b / 2), 2) )));
    
    dst = dst * EARTH_R;
    //  dst= round(dst * 10000) / 10000;
    return dst;
}

double get_distanceAccountAltitude(double lat1, double lng1,double alt1, double lat2, double lng2,double alt2)
{
    double platDis = get_distance(lat1, lng1, lat2, lng2);
    double dis = sqrt(pow(platDis, 2) + pow(fabs(alt1-alt2), 2));
    
    return dis;
}



inline double calculateDistanceBetweenPoints(LocationPointType p1, LocationPointType p2, bool accountAltitude)
{
    double distance = 0;
    if(accountAltitude)
    {
        distance = get_distanceAccountAltitude(p1.latitude, p1.longitude, p1.altitude, p2.latitude, p2.longitude, p2.altitude);
    }
    else
    {
        distance = get_distance(p1.latitude, p1.longitude, p2.latitude, p2.longitude);
    }
    
    return distance;
}

inline double calculateDistanceBetweenCoordinates(CLLocationCoordinate2D p1, CLLocationCoordinate2D p2)
{
    double distance = get_distance(p1.latitude, p1.longitude, p2.latitude, p2.longitude);
    
    return distance;
}

struct CommPointStruct {
    double x;
    double y;
};
typedef struct CommPointStruct CommPoint;

inline bool lineCrossOverRectRegion(double rectOriginalX,double rectOriginalY,double rectWidth, double rectHeight, double p1x, double p1y, double p2x,double p2y)
{
    register double minX = rectOriginalX;
    register double maxX = minX + rectWidth;
    register double minY = rectOriginalY;
    register double maxY = minY + rectHeight;
    
    CommPoint linePoint1 = {p1x,p1y};
    CommPoint linePoint2 = {p2x,p2y};
    
    if(   (linePoint1.x<minX && linePoint2.x<minX)
       || (linePoint1.x>maxX && linePoint2.x>maxX)
       || (linePoint1.y>maxY && linePoint2.y>maxY)
       || (linePoint1.y<minY && linePoint2.y<minY)
       )
    {
        return false;
    }
    
    
    if((linePoint1.x<=maxX && linePoint1.x>=minX) && (linePoint1.y >= minY && linePoint1.y <= maxY) &&
       ((linePoint2.x<=maxX && linePoint2.x>=minX) && (linePoint2.y >= minY && linePoint2.y <= maxY)))
        return true;
    
    double dlx = linePoint2.x - linePoint1.x;
    double dly = linePoint2.y - linePoint1.y;
    
    if(linePoint1.x < minX)
    {
        //由于第一步已经排除了一些条件，这里只要不会和最左边的竖边相交即可
        double y1 = fabs((minX - linePoint1.x)/dlx) * dly + linePoint1.y;
        if(y1>=minY && y1<=maxY)
            return true;
    }
    else if(linePoint1.x > minX && linePoint1.x < maxX)
    {
        double y1 = fabs((linePoint1.x - minX)/dlx) * dly + linePoint1.y;
        if(y1>=minY && y1<=maxY)
            return true;
        
        double y2 = fabs((maxX - linePoint1.x)/dlx) * dly + linePoint1.y;
        if(y2>=minY && y2<=maxY)
            return true;
    }
    else if(linePoint1.x>=maxX)
    {
        double y2 = fabs((linePoint1.x - maxX)/dlx) * dly + linePoint1.y;
        if(y2>=minY && y2<=maxY)
            return true;
    }
    
    if(linePoint1.y < minY)
    {
        double x1 = fabs((minY - linePoint1.y)/dly) * dlx + linePoint1.x;
        if(x1>=minX && x1<=maxX)
            return true;
    }
    else if(linePoint1.y > minY && linePoint1.y < maxY)
    {
        double x1 = fabs((minY - linePoint1.y)/dly) * dlx + linePoint1.x;
        if(x1>=minX && x1<=maxX)
            return true;
        
        double x2 = fabs((linePoint1.y - maxY)/dly) * dlx + linePoint1.x;
        if(x2>=minX && x2<=maxX)
            return true;
    }
    else if(linePoint1.y>=maxY)
    {
        double x2 = fabs((linePoint1.y - maxY)/dly) * dlx + linePoint1.x;
        if(x2>=minX && x2<=maxX)
            return true;
    }
    
    
    return false;
}

CLLocationCoordinate2D CLLocationCoordinate2DFromPointDataType(LocationPointType point)
{
    
    CLLocationCoordinate2D cord;
    cord.latitude = point.latitude;
    cord.longitude = point.longitude;
    return cord;
}

inline bool LineCorssOverMapRect(MKMapRect rect, MKMapPoint linePoint1,MKMapPoint linePoint2)
{
    return lineCrossOverRectRegion(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, linePoint1.x, linePoint1.y, linePoint2.x, linePoint2.y);
}

